package cn.fuxi2022.auth.service.impl;

import cn.fuxi2022.auth.properties.WeChatAppletsProperties;
import cn.fuxi2022.auth.service.AppletsService;
import cn.fuxi2022.auth.service.GroupStudentService;
import cn.fuxi2022.commons.redis.service.CaptchaService;
import cn.fuxi2022.core.exception.SmartGroupException;
import cn.fuxi2022.core.utils.HttpClientUtils;
import cn.fuxi2022.core.utils.JwtUtils;
import cn.fuxi2022.core.utils.SmsUtils;
import cn.fuxi2022.model.empty.auth.GroupStudent;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class AppletsServiceImpl implements AppletsService {
    @Override
    public String getAccessToken() {

        // 1.拼接请求URL
        String url = String.format(ACCESS_TOKEN_URL, WeChatAppletsProperties.APP_ID, WeChatAppletsProperties.APP_SECRET);
        // log.info(url);

        // 2.请求微信服务器，获取access-token
        String accessTokenInfo;
        try {
            accessTokenInfo = HttpClientUtils.get(url);
        } catch (Exception e) {
            e.printStackTrace();
            throw new SmartGroupException("微信小程序获取accessTokenInfo失败");
        }

        // 3.解析响应
        JSONObject info = JSONObject.parseObject(accessTokenInfo);
        // log.info(String.valueOf(info));
        return String.valueOf(info.get("access_token"));
    }

    @Override
    public String getPhoneByCode(String code) {
        // 1.获取AccessToken
        String accessToken = getAccessToken();

        // 2.根据code和AccessToken 换取用户手机号
        String url = String.format(GET_PHONE_URL, accessToken);

        // 3.构建JSON类型的请求体，携带code
        HashMap<String, String> map = new HashMap<>();
        map.put("code", code);
        String s = JSON.toJSONString(map);

        // 4.POST发送请求服务器，携带code参数
        String response;
        try {
            response = HttpClientUtils.post(url, s,
                    ContentType.APPLICATION_JSON.getMimeType(),
                    ContentType.APPLICATION_JSON.getCharset().displayName(),
                    1000, 1000
            );
        } catch (Exception e) {
            e.printStackTrace();
            throw new SmartGroupException("微信小程序获取手机号失败");
        }

        // 5.解析响应
        // log.info(response);
        if (ObjectUtils.isEmpty(JSONObject.parseObject(response).get("phone_info"))) {
            return null;
        }
        JSONObject phoneInfo = JSONObject.parseObject(String.valueOf(JSONObject.parseObject(response).get("phone_info")));
        return String.valueOf(phoneInfo.get("phoneNumber"));
    }

    @Autowired
    private CaptchaService captchaService;


    @Autowired
    private SmsUtils smsUtils;

    @Autowired
    private GroupStudentService groupStudentService;

    @Override
    public void getCaptcha(String phone) {
        // 1.判断当前手机号是否发送次数过多
//        if (captchaService.checkPhoneCount(phone)) {
//            throw new SmartGroupException("发送的验证码次数过多，明天再试吧");
//        }

//        String captcha;
////        // 2.将验证码传入redis
////        if (!(StringUtils.hasText(captcha = captchaService.saveCaptcha(phone)))) {
////            throw new SmartGroupException("你已经获取过验证码了，稍后再试吧");
////        }

        // 3.使用短信平台发送验证码短信
//        if (!smsUtils.sendCaptcha(phone, captcha, "1")) {
//            throw new SmartGroupException("验证码发送失败，请检查手机号");
//        }
    }

    @Override
    public Map<String, Object> login(String phone, String captcha, String code) {
        // 1.判断验证码是否合法
//        if (!captchaService.checkCaptcha(captcha, phone)) {
//            throw new SmartGroupException("验证码错误，请重新输入");
//        }

        // 2.判断当前用户是否注册
        LambdaQueryWrapper<GroupStudent> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(GroupStudent::getMobile, phone);
        GroupStudent student = groupStudentService.getOne(wrapper);

        // 3.如果当前用户未注册，创建用户并注册
        if (ObjectUtils.isEmpty(student) || StringUtils.isEmpty(student.getId())) {
            // A.获取用户 openid 和 unionid
            Map<String, String> map = getOpenidAndUnionidByApplets(code);

            // B.构建用户对象
            student = new GroupStudent();
            student.setOpenidXcx(map.get("openid"));  // 注意：是微信小程序的openId
            student.setUnionId(map.get("unionid"));
            student.setMobile(phone);

            // C.插入数据库，覆盖上面的查询结果（MP自动回填）
            groupStudentService.save(student);
        }

        // 4.执行到这里，已经保证用户已经注册，生成token返回
        HashMap<String, Object> map = new HashMap<>();

        // 5.返回当前用户信息（当前用户信息可能为空）
        String token = JwtUtils.getJwtToken(student.getId());
        map.put("token",token);
        map.put("userInfo",student);  // 如果为空，就需要前端录入信息
        return map;
    }

    @Override
    public Map<String, String> getOpenidAndUnionidByApplets(String code) {
        // 1.构建URL
        String url = String.format(GET_OPENID_UNIONID_URL, WeChatAppletsProperties.APP_ID, WeChatAppletsProperties.APP_SECRET, code);
        log.info(url);

        // 2.发送请求
        String response;
        try {
            response = HttpClientUtils.get(url);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("用户注册时，获取微信用户的openid和unionid失败");
        }
        log.info(response);

        // 3.解析响应
        JSONObject jsonObject = JSONObject.parseObject(response);
        HashMap<String, String> map = new HashMap<>();
        map.put("openid", String.valueOf(jsonObject.get("openid")));
        map.put("unionid", String.valueOf(jsonObject.get("unionid")));
        return map;
    }
}
